﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace NExplorer.Controls
{
	internal class ToolStripItemCommandManager : IDisposable
	{
		private readonly ToolStripItem	_item;
		private readonly ICommand		_command;
        private readonly Keys           _keys;

        public ToolStripItemCommandManager(ToolStripItem item, ICommand command)
            : this(item, command, Keys.None)
        {}

	    public ToolStripItemCommandManager(ToolStripItem item, ICommand command, Keys keys)
		{
			_item = item;
			_command = command;
            _keys = keys;

			_command.TextChanged += WhenTextChanged;
			_command.EnabledChanged += WhenEnabledChanged;
			_command.ImageChanged += WhenImageChanged;

			SetText();
			SetEnabled();
			SetImage();
		}

		public void ExecuteCommand()
		{
			_command.Execute();
		}

		public ICommand Command
		{
			get { return _command; }
		}

	    private void SetEnabled()
		{
			_item.Enabled = _command.Enabled;
		}

		private void SetText()
		{
			_item.Text = _command.Text;

		    ToolStripButton button = _item as ToolStripButton;

            if (button != null && _keys != Keys.None)
            {
                Keys keys = _keys;
                List<string> words = new List<string>();

                if ((keys & Keys.Shift) == Keys.Shift)
                {
                    words.Add("Shift");
                    keys ^= Keys.Shift;
                }

                if ((keys & Keys.Control) == Keys.Control)
                {
                    words.Add("Ctrl");
                    keys ^= Keys.Control;
                }

                if ((keys & Keys.Alt) == Keys.Alt)
                {
                    words.Add("Alt");
                    keys ^= Keys.Alt;
                }

                words.Add(keys.ToString());

                button.ToolTipText = string.Format("{0} ({1})", _command.Text, string.Join(" + ", words.ToArray()));
            }
		}

		private void SetImage()
		{
			_item.Image = _command.Image;
		}

		private void WhenImageChanged(object sender, EventArgs e)
		{
			SetImage();
		}

		private void WhenEnabledChanged(object sender, EventArgs e)
		{
			SetEnabled();
		}

		private void WhenTextChanged(object sender, EventArgs e)
		{
			SetText();
		}

		public void Dispose()
		{
            _command.Dispose();
			_command.TextChanged -= WhenTextChanged;
			_command.EnabledChanged -= WhenEnabledChanged;
			_command.ImageChanged -= WhenImageChanged;
		}
	}
}
